package com.androidgame.fx.impl;

import java.util.List;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.androidgame.fx.Input.TouchEvent;

public class AndroidFastRenderView 
	extends SurfaceView implements Runnable {
	
    AndroidGame 		game;			// 액티비티와 게임 자원에 접근하기 위한 참조입니다.
    Bitmap 				framebuffer;	// 이미지를 그려넣을 버퍼입니다.
    Thread 				renderThread;	// 서브 스레드입니다.
    volatile boolean 	running;		// 서브 스레드의 상태에 관련한 변수입니다.
    SurfaceHolder 		holder;			// SurfaceView를 사용하기 위한 Holder입니다.
    
    /***
     * 생성자 입니다.
     * @param game : 액티비티와 게임 자원에 접근하기 위한 참조입니다.
     * @param framebuffer : 이미지를 그려넣을 버퍼입니다.
     */
    public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer) {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.renderThread = null;
        this.running = false;
        this.holder = getHolder();
    }

    // 액티비티가 재개되는 시점에 호출되는 함수입니다.
    public void resume() {
        running = true;
        renderThread = new Thread(this);
        renderThread.start();         
    }      

    // 액티비티가 일시 정지되는 시점에 호출되는 함수입니다.
    public void pause() {                        
        running = false;                        
        while(true) {
            try {
                renderThread.join();
                break;
            } catch (InterruptedException e) {
                // retry
            }
        }
    }
    
    public void run() {
        Rect dstRect = new Rect();
        long startTime = System.nanoTime();
        while(running) {  
            if(!holder.getSurface().isValid())
                continue;           
            
            float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
            startTime = System.nanoTime();

            processTouchEvents();
            game.getGameTime().update();
            // 현재 스크린의 업데이트
            game.getCurrentScreen().update(deltaTime);
            // 현재 스크린의 그리기 (스크린은 framebuffer에 그리기 작업을 수행함.)
            game.getCurrentScreen().present(deltaTime);
            
            Canvas canvas = holder.lockCanvas();
            
            // 화면의 사각형 크기를 얻어옵니다.
        	canvas.getClipBounds(dstRect);
        	// 스크린이 그린 framebuffer를 화면 크기에 맞추어 그립니다.
        	canvas.drawBitmap(framebuffer, null, dstRect, null);
       
        	holder.unlockCanvasAndPost(canvas);
        }
    }
    
    private void processTouchEvents() {
    	List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
    	game.getInput().getKeyEvents();
    	
    	for(int i = 0; i < touchEvents.size(); i++) {
    		TouchEvent event = touchEvents.get(i);
    		
    		if(event.type == TouchEvent.TOUCH_DOWN) {
    			if(game.getCurrentScreen().touchDown(event)) break;
    		} else if(event.type == TouchEvent.TOUCH_DRAGGED) {
    			if(game.getCurrentScreen().touchDragged(event)) break;
    		} else if(event.type == TouchEvent.TOUCH_UP) {
    			if(game.getCurrentScreen().touchUp(event)) break;
    		}
    	}
    }
    
    public void setFrameBuffer(Bitmap frameBuffer) {
    	this.framebuffer = frameBuffer;
    }
}